package com.chenjun.designpattern.structural.facade;

/**
 * 举JDBC编程的一个例子 JDBC的获取连接 Connection conn = DriverManager.getConnection(驱动名称)
 * 就是一个外观模式的例子
 * <h3>简单来说，该模式就是把一些复杂的流程封装成一个接口供给外部用户更简单的使用。这个模式中，设计到3个角色。<br/>
 * 1）.门面角色：外观模式的核心。它被客户角色调用，它熟悉子系统的功能。内部根据客户角色的需求预定了几种功能的组合。<br/>
 * 2）.子系统角色:实现了子系统的功能。它对客户角色和Facade时未知的。它内部可以有系统内的相互交互，也可以由供外界调用的接口。<br/>
 * 3）.客户角色:通过调用Facede来完成要实现的功能。
 * <h3>
 * 
 * 
 * <p>
 * 外观模式的优点
•对客户屏蔽子系统组件，减少了客户处理的对象数目并使得子系统使用起来更加容易。同时，客户代码变简单
• 实现了子系统与客户之间的松耦合关系。       
   降低了大型软件系统中的编译依赖性，并简化了系统在不同平台之间的移植过程。
•只是提供了一个访问子系统的统一入口，并不影响用户直接使用子系统类。
 
外观模式的缺点
•不能很好地限制客户使用子系统类，如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
•在不引入抽象外观类的情况下，增加新的子系统可能需要修改外观类或客户端的源代码，违背了“开闭原则”。
w模式适用环境
在以下情况下可以使用外观模式：
•当要为一个复杂子系统提供一个简单接口时可以使用外观模式。
•客户程序与多个子系统之间存在很大的依赖性。
•在层次化结构中，可以使用外观模式定义系统中每一层的入口，层与层之间不直接产生联系，而通过外观类建立联系，降低层之间的耦合度。
模式扩展
一个系统有多个外观类
•在外观模式中，通常只需要一个外观类，并且此外观类只有一个实例，换言之它是一个单例类。在很多情况下为了节约系统资源，一般将外观类设计为单例类。当然这并不意味着在整个系统里只能有一个外观类，在一个系统中可以设计多个外观类，每个外观类都负责和一些特定的子系统交互，向用户提供相应的业务功能。
w模式扩展注意
不要试图通过外观类为子系统增加新行为
•不要通过继承一个外观类在子系统中加入新的行为，这种做法是错误的。
•外观模式的用意：为子系统提供一个集中化和简化的沟通渠道
外观模式与迪米特法则
•外观模式创造出一个外观对象，将客户端所涉及的属于一个子系统的协作伙伴的数量减到最少，使得客户端与子系统内部的对象的相互作用被外观对象所取代。
•外观模式就是实现代码重构以便达到“迪米特法则”要求的一个强有力的武器。
 
抽象外观类的引入
•外观模式最大的缺点在于违背了“开闭原则”，当增加新的子系统或者移除子系统时需要修改外观类，可以通过引入抽象外观类在一定程度上解决该问题，客户端针对抽象外观类进行编程。
 * </p>
 * @author admin
 *
 */
public class 外观模式
{

	public static void main(String[] args)
	{
		Computer computer = new Computer();
		computer.startup();
		computer.shutdown();
	}

}

class CPU
{
	public void startup()
	{
		System.out.println("CPU上电");
	}

	public void shutdown()
	{
		System.out.println("CPU断电");
	}
}

class Memory
{
	public void startup()
	{
		System.out.println("内存上电");
	}

	public void shutdown()
	{
		System.out.println("内存断电");
	}
}

class Disk
{
	public void startup()
	{
		System.out.println("硬盘开转");
	}

	public void shutdown()
	{
		System.out.println("硬盘停转");
	}
}

class Computer
{
	private CPU cpu = new CPU();
	private Disk disk = new Disk();
	private Memory memory = new Memory();

	// 声明对象
	public void startup()
	{
		cpu.startup();
		memory.startup();
		disk.startup();
	}

	public void shutdown()
	{
		cpu.shutdown();
		memory.shutdown();
		disk.shutdown();
	}
}
